/* Basirudin Rachman - 2011
 * b@rachmans.com
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Navigation;
using Imtihan.Web;

namespace Imtihan
{
    public class ProblemAnswers
    {
        public Problem Problem { get; set; }
        public List<Answer> Answers { get; set; }
        public Dictionary<Guid, bool> IsAnswerChecks { get; set; }
    }

    public class TabConverter : IValueConverter
    {
        List<ProblemAnswers> _source = new List<ProblemAnswers>();
        List<TabItem> _result = new List<TabItem>();

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            _source = value as List<ProblemAnswers>;
            if (_source != null)
            {
                //List<TabItem> result = new List<TabItem>();

                int i = 1;
                foreach (ProblemAnswers tab in _source)
                {
                    TabItem ti = new TabItem()
                    {
                        Header = new TextBlock() { Text = i.ToString(), Foreground = new SolidColorBrush(Colors.Red), Name = string.Format("Tab_{0}", tab.Problem.Id)
                            , FontWeight = FontWeights.Bold }
                    };

                    StackPanel sp = new StackPanel();
                    ti.Content = sp;

                    sp.Children.Add(new TextBlock() { Text = tab.Problem.Question.Sentence });

                    if (tab.Answers != null)
                    {
                        foreach (Answer a in tab.Answers)
                        {
                            if (a != null)
                            {
                                StackPanel spi = new StackPanel { Orientation = Orientation.Horizontal };

                                CheckBox cb = new CheckBox() { VerticalAlignment = VerticalAlignment.Top, Name = string.Format("Ans_{0}_{1}", tab.Problem.Id, a.Id) };
                                cb.Click += new RoutedEventHandler(cb_Click);
                                spi.Children.Add(cb);

                                TextBlock tb = new TextBlock { Text = a.Words };
                                spi.Children.Add(tb);

                                sp.Children.Add(spi);
                            }
                        }

                        Button bt = new Button { Content = "Submit", Name = string.Format("Bt_{0}", tab.Problem.Id), HorizontalAlignment = HorizontalAlignment.Center };
                        bt.Click += new RoutedEventHandler(bt_Click);
                        sp.Children.Add(bt);

                    }
                    _result.Add(ti);
                    i++;
                }
                return _result;
            }
            return null;
        }

        Brush _defaultBackgroundColor;

        void cb_Click(object sender, RoutedEventArgs e)
        {
            CheckBox cb = sender as CheckBox;

            string[] cbNames = cb.Name.Split(new char[] { '_' });

            //  Problem Id.
            Guid problemId = Guid.Parse(cbNames[1]);

            //  Answer Id.
            Guid answerId = Guid.Parse(cbNames[2]);

            //  Get Problem Answer.
            ProblemAnswers pa = _source.Where(pAnswers => pAnswers.Problem.Id == problemId).SingleOrDefault();

            //  Set answers.
            pa.IsAnswerChecks[answerId] = cb.IsChecked.Value;

            //  Change title.
            int isAnyAnswerSelected = pa.IsAnswerChecks.Values.Count(isAnswer => isAnswer);

            TabItem ti = ((cb.Parent as StackPanel).Parent as StackPanel).Parent as TabItem;

            if (isAnyAnswerSelected > 0)
            {
                (ti.Header as TextBlock).Foreground = new SolidColorBrush(Colors.Yellow);
                if (_defaultBackgroundColor == null)
                {
                    _defaultBackgroundColor = ti.Background;
                }
                ti.Background = new SolidColorBrush(Colors.Blue);
            }
            else
            {
                (ti.Header as TextBlock).Foreground = new SolidColorBrush(Colors.Red);
                ti.Background = _defaultBackgroundColor;
            }
        }

        void bt_Click(object sender, RoutedEventArgs e)
        {
            Button bt = sender as Button;

            string[] btNames = bt.Name.Split(new char[] { '_' });

            //  Problem Id.
            Guid problemId = Guid.Parse(btNames[1]);

            //  Get Problem Answer.
            ProblemAnswers pa = _source.Where(pAnswers => pAnswers.Problem.Id == problemId).SingleOrDefault();

            //  Get the index.
            int idxNext = _source.IndexOf(pa);
            if (idxNext < _source.Count - 1)
            {
                idxNext += 1;
            }
            else
            {
                idxNext = 0;
            }

            if (pa.IsAnswerChecks.Values.Count(isAnswer => isAnswer) > 0)
            {
                ImtihanDomainContext context = new ImtihanDomainContext();

                context.Load(context.GetUserAnswerByProblemAndUserIdQuery(pa.Problem.Id, UserManager.Instance.Id), (opLoadUserAnswer) =>
                {
                    if (!opLoadUserAnswer.HasError)
                    {
                        foreach (UserAnswer ua in opLoadUserAnswer.Entities)
                        {
                            context.UserAnswers.Remove(ua);
                        }

                        context.SubmitChanges((opRemove) =>
                        {
                            if (!opRemove.HasError)
                            {
                                foreach (Guid k in pa.IsAnswerChecks.Keys)
                                {
                                    if (pa.IsAnswerChecks[k])
                                    {
                                        Answer a = pa.Answers.Where(pAnswer => pAnswer.Id == k).SingleOrDefault();
                                        if (a != null)
                                        {
                                            context.UserAnswers.Add(new UserAnswer { ProblemId = pa.Problem.Id, UserId = UserManager.Instance.Id, AnswerId = a.Id
                                                , Id = Guid.NewGuid() });
                                        }
                                    }
                                }

                                context.SubmitChanges((opSubmit) =>
                                {
                                    if (!opSubmit.HasError)
                                    {
                                        MessageBox.Show("Your answer has been submitted");

                                        TabItem ti = (bt.Parent as StackPanel).Parent as TabItem;
                                        (ti.Header as TextBlock).Foreground = new SolidColorBrush(Colors.Green);
                                        ti.Background = _defaultBackgroundColor;

                                        //  Go to the next item to be selected.
                                        TabItem tiNext = _result[idxNext];
                                        tiNext.IsSelected = true;
                                    }
                                }, null);
                            }
                        }, null);
                    }
                }, null);

            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }


    public partial class ExamProblem : Page
    {
        ImtihanDomainContext _context = new ImtihanDomainContext();
        List<ProblemAnswers> randomizedProblem = new List<ProblemAnswers>();

        private int _processNumber = 0;
        private object _obj = new object();
        private int _numberOfProblem = 0;

        public ExamProblem()
        {
            InitializeComponent();
        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //  Get assessment id.
            Guid assessmentId = Guid.Empty;
            string[] uris = e.Uri.OriginalString.Split(new char[] { '?' });
            if (uris.Length <= 1)
            {
                MessageBox.Show("No assessment id provided");
            }
            else
            {
                string[] assessmentInformation = uris[1].Split(new char[] { '=' });
                if (assessmentInformation.Length == 2)
                {
                    assessmentId = Guid.Parse(assessmentInformation[1]);
                }
            }

            //  Select categories for this assessment.
            _context.Load(_context.GetAssessmentCategoriesQuery(), (opLoad) =>
            {
                if (!opLoad.HasError)
                {
                    var varCategories = from acEntities in opLoad.Entities
                                               where acEntities.AssessmentId == assessmentId
                                               select acEntities.Category;

                        _context.Load(_context.GetProblemsQuery(), (opLoadProblem) =>
                        {
                            if (!opLoadProblem.HasError)
                            {
                                var problemQuestions = from entities in opLoadProblem.Entities
                                               where varCategories.Contains(entities.Category)
                                               select entities.QuestionId;

                                _context.Load(_context.GetQuestionsQuery(), (opLoadQuestion) =>
                                {
                                    var pqs = from qEntities in opLoadQuestion.Entities
                                              from pqEntities in opLoadProblem.Entities
                                              where qEntities.Id == pqEntities.QuestionId
                                              select new Problem { Question = qEntities, Id = pqEntities.Id };

                                    _numberOfProblem = pqs.Count();
                                    List<Problem> normalSequence = pqs.ToList();
                                    randomizedProblem = new List<ProblemAnswers>(_numberOfProblem);

                                    for (int i = 0; i < _numberOfProblem; i++)
                                    {

                                        //  Random value.
                                        Random random = new Random();
                                        int randomizedSequence = random.Next(1, _numberOfProblem - i);

                                        ProblemAnswers p = new ProblemAnswers() { Problem = normalSequence[randomizedSequence - 1] };

                                        _context.Load(_context.GetAnswerByProblemIdQuery(p.Problem.Id), (opLoadProblemAnswer) =>
                                        {
                                            var pAnswers = from paEntities in opLoadProblemAnswer.Entities
                                                           select paEntities;

                                            p.Answers = pAnswers.ToList();
                                            p.IsAnswerChecks = new Dictionary<Guid, bool>(p.Answers.Count);
                                            foreach (Answer a in p.Answers)
                                            {
                                                p.IsAnswerChecks.Add(a.Id, false);
                                            }
                                            opLoadProblemAnswer.Completed += new EventHandler(opLoadProblemAnswer_Completed);
                                        }, null);

                                        randomizedProblem.Add(p);
                                        normalSequence.RemoveAt(randomizedSequence - 1);
                                    }
                                }, null);
                            }
                        }, null);
                }
            }, null);
        }

        void opLoadProblemAnswer_Completed(object sender, EventArgs e)
        {
            lock (_obj)
            {
                _processNumber++;
                if (_processNumber == _numberOfProblem)
                {
                    tabExam.DataContext = randomizedProblem;
                }
            }
        }
    }
}
